/* EasyWay Game Engine
 * Copyright (C) 2007 Daniele Paggi.
 *  
 * Written by: 2007 Daniele Paggi<dshnt@hotmail.com>
 *   
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 * 
 * You should have received a copy of the GNU Library General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

package org.easyway.lists.linked;

import java.io.Serializable;

import org.easyway.interfaces.base.IBaseObject;
import org.easyway.interfaces.base.IList;
import org.easyway.objects.BaseObject;

public class BaseLinkedList<T extends IBaseObject> extends BaseObject implements
		IList<T>, Serializable {

	private static final long serialVersionUID = 2076531540807338042L;

	Entry<T> first;

	Entry<T> last;

	int count;

	Entry<T> indexScan;

	/**
	 * creates a new instace
	 */
	public BaseLinkedList() {
		first = last = new Entry<T>(null, null, null, this);
		indexScan = null;
		type.set("$_BASELINKEDLIST");
		count = 0;
	}

	public void add(T obj) { // O( 1 )
		if (count == 0) {
			Entry<T> entry = new Entry<T>(null, null, obj, this);
			last.prev = entry;
			first.next = entry;
		} else {
			// add the object at end of list
			Entry<T> mlast = getLast();
			mlast.next = new Entry<T>(null, mlast, obj, this);
		}
		++count;
	}

	public void add(T obj, int index) { // O( n/2 )
		if (count == 0) {
			Entry<T> entry = new Entry<T>(null, null, obj, this);
			last.prev = entry;
			first.next = entry;
		} else {
			if (index == 0) {
				// add the object in the first position
				Entry<T> mfirst = getFirst();
				first.next = mfirst.prev = new Entry<T>(mfirst, null, obj, this);
			} else if (index >= count) {
				// add the object in the last position
				Entry<T> mlast = getLast();
				last.prev = mlast.next = new Entry<T>(null, mlast, obj, this);
			} else {
				if (index >= count / 2) {
					int i = count - 2;
					Entry<T> current = getLast();
					while (i != index) {
						current = current.prev;
						--i;
					}
					current.prev = (current.prev.next = (new Entry<T>(
							current.prev, current, obj, this)));

				} else {
					// assert index<count;
					int i = 1; // note: I'll start counting from 1 and not from
					// 0
					Entry<T> current = getFirst();
					while (i != index) {
						current = current.next;
						++i;
					}
					current.next = (current.next.prev = (new Entry<T>(
							current.next, current, obj, this)));
				}
			}
		}
		++count;
	}

	public int contains(T obj) { // O( n )
		// TODO Auto-generated method stub
		return 0;
	}

	public T get(int index) { // O( n )
		// TODO Auto-generated method stub
		return null;
	}

	public T getCurrent() {
		// TODO Auto-generated method stub
		return null;
	}

	public int indexOf(T obj) {
		// TODO Auto-generated method stub
		return 0;
	}

	public boolean next() {
		// TODO Auto-generated method stub
		return false;
	}

	public void remove(IBaseObject obj) {
		// TODO Auto-generated method stub

	}

	public void remove(int index) {
		// TODO Auto-generated method stub

	}

	public int size() {
		// TODO Auto-generated method stub
		return 0;
	}

	public void startScan() {
		// TODO Auto-generated method stub

	}

	public void startScan(int index) {
		// TODO Auto-generated method stub

	}

	public Entry<T> getFirst() {
		return first.next;
	}

	public Entry<T> getLast() {
		return last.prev;
	}

}
